/**
 * 事件驱动组件基类
 * 为组件提供事件通信能力，替代直接的getComponent依赖
 */

import component from '../../core/tool/component';
import { ComponentEventBus, ComponentEvent, EventPriority } from './ComponentEventBus';
import { COMPONENT_EVENTS, ComponentEventDataMap, ComponentEventFactory } from './ComponentEvents';
import { ServiceLogger } from '../logging/UnifiedLogger';
import { createServiceErrorHandler } from '../error/ErrorHandlingInitializer';

/**
 * 事件驱动组件基类
 * 继承此类的组件将获得事件通信能力
 */
export abstract class EventDrivenComponent extends component {
    protected eventBus: ComponentEventBus;
    protected logger: ServiceLogger;
    protected errorHandler: any;
    private eventListenerIds: string[] = [];
    private componentName: string;

    constructor() {
        super();
        this.eventBus = ComponentEventBus.getInstance();
        this.componentName = this.constructor.name;
        this.logger = new ServiceLogger('EventDrivenComponent', this.componentName);
        this.errorHandler = createServiceErrorHandler(this.componentName);
        
        // 在组件初始化时注册默认事件监听器
        this.setupEventListeners();
    }

    /**
     * 设置事件监听器 - 子类重写此方法来注册事件监听
     */
    protected setupEventListeners(): void {
        // 子类在此方法中注册事件监听器
        // 例如：this.onEvent(COMPONENT_EVENTS.EQUIPMENT.EQUIPPED, this.handleEquipmentEquipped.bind(this));
    }

    /**
     * 注册事件监听器
     */
    protected onEvent<K extends keyof ComponentEventDataMap>(
        eventType: K,
        handler: (data: ComponentEventDataMap[K], event: ComponentEvent) => Promise<void> | void,
        options: {
            priority?: EventPriority;
            once?: boolean;
        } = {}
    ): string {
        const wrappedHandler = async (event: ComponentEvent) => {
            try {
                this.logger.debug(`Handling event: ${eventType}`, {
                    metadata: { eventId: event.eventId, source: event.source }
                });
                
                await handler(event.data, event);
                
            } catch (error) {
                const gameError = this.errorHandler.handleError(error, `handleEvent_${eventType}`);
                this.logger.error(`Event handler failed: ${eventType}`, gameError, {
                    metadata: { eventId: event.eventId, source: event.source }
                });
                
                // 发射错误事件
                this.emitSystemError(gameError, `Event handler failed: ${eventType}`);
            }
        };

        const listenerId = this.eventBus.on(
            eventType,
            this.componentName,
            wrappedHandler,
            options
        );

        this.eventListenerIds.push(listenerId);
        
        this.logger.debug(`Event listener registered: ${eventType}`, {
            metadata: { listenerId, priority: options.priority }
        });

        return listenerId;
    }

    /**
     * 注册一次性事件监听器
     */
    protected onceEvent<K extends keyof ComponentEventDataMap>(
        eventType: K,
        handler: (data: ComponentEventDataMap[K], event: ComponentEvent) => Promise<void> | void,
        priority: EventPriority = EventPriority.NORMAL
    ): string {
        return this.onEvent(eventType, handler, { once: true, priority });
    }

    /**
     * 发射事件
     */
    protected async emitEvent<K extends keyof ComponentEventDataMap>(
        eventType: K,
        data: ComponentEventDataMap[K],
        options: {
            cancelable?: boolean;
            timeout?: number;
        } = {}
    ): Promise<ComponentEvent> {
        try {
            this.logger.debug(`Emitting event: ${eventType}`, {
                metadata: { dataKeys: Object.keys(data || {}) }
            });

            return await this.eventBus.emit(
                eventType,
                this.componentName,
                data,
                options
            );
        } catch (error) {
            const gameError = this.errorHandler.handleError(error, `emitEvent_${eventType}`);
            this.logger.error(`Failed to emit event: ${eventType}`, gameError);
            throw gameError;
        }
    }

    /**
     * 发射同步事件
     */
    protected emitEventSync<K extends keyof ComponentEventDataMap>(
        eventType: K,
        data: ComponentEventDataMap[K]
    ): ComponentEvent {
        try {
            return this.eventBus.emitSync(eventType, this.componentName, data);
        } catch (error) {
            const gameError = this.errorHandler.handleError(error, `emitEventSync_${eventType}`);
            this.logger.error(`Failed to emit sync event: ${eventType}`, gameError);
            throw gameError;
        }
    }

    /**
     * 移除事件监听器
     */
    protected offEvent(listenerId: string): boolean {
        const removed = this.eventBus.off(listenerId);
        if (removed) {
            const index = this.eventListenerIds.indexOf(listenerId);
            if (index >= 0) {
                this.eventListenerIds.splice(index, 1);
            }
        }
        return removed;
    }

    /**
     * 发射系统错误事件
     */
    protected emitSystemError(error: Error, message?: string): void {
        try {
            const errorData = ComponentEventFactory.createSystemError(
                this.componentName,
                error,
                this.id // 使用组件的玩家ID
            );

            this.eventBus.emitSync(
                COMPONENT_EVENTS.SYSTEM.ERROR_OCCURRED,
                errorData
            );
        } catch (emitError) {
            // 避免错误事件本身导致错误
            this.logger.error('Failed to emit system error event', emitError);
        }
    }

    /**
     * 组件销毁时清理事件监听器
     */
    destroy(): void {
        // 移除所有事件监听器
        this.eventListenerIds.forEach(id => this.eventBus.off(id));
        this.eventListenerIds = [];

        // 发射组件销毁事件
        try {
            this.eventBus.emitSync(
                COMPONENT_EVENTS.SYSTEM.COMPONENT_DESTROYED,
                ComponentEventFactory.createSystemError(this.componentName, new Error('Component destroyed'), this.id)
            );
        } catch (error) {
            this.logger.error('Failed to emit component destroyed event', error);
        }

        this.logger.info('Component destroyed and events cleaned up');
        
        // 调用父类销毁方法
        if (super.destroy) {
            super.destroy();
        }
    }

    // ==================== 便捷事件发射方法 ====================

    /**
     * 发射装备穿戴事件
     */
    protected emitEquipmentEquipped(equipment: any, slot?: number): Promise<ComponentEvent> {
        return this.emitEvent(
            COMPONENT_EVENTS.EQUIPMENT.EQUIPPED,
            ComponentEventFactory.createEquipmentEquipped(this.id, equipment, slot)
        );
    }

    /**
     * 发射装备卸载事件
     */
    protected emitEquipmentUnequipped(equipment: any, slot?: number): Promise<ComponentEvent> {
        return this.emitEvent(
            COMPONENT_EVENTS.EQUIPMENT.UNEQUIPPED,
            ComponentEventFactory.createEquipmentUnequipped(this.id, equipment, slot)
        );
    }

    /**
     * 发射装备替换事件
     */
    protected emitEquipmentReplaced(newEquipment: any, oldEquipment: any, slot?: number): Promise<ComponentEvent> {
        return this.emitEvent(
            COMPONENT_EVENTS.EQUIPMENT.REPLACED,
            ComponentEventFactory.createEquipmentReplaced(this.id, newEquipment, oldEquipment, slot)
        );
    }

    /**
     * 发射物品添加事件
     */
    protected emitItemAdded(item: any, reason?: string): Promise<ComponentEvent> {
        return this.emitEvent(
            COMPONENT_EVENTS.BAG.ITEM_ADDED,
            ComponentEventFactory.createItemAdded(this.id, item, reason)
        );
    }

    /**
     * 发射物品移除事件
     */
    protected emitItemRemoved(item: any, reason?: string): Promise<ComponentEvent> {
        return this.emitEvent(
            COMPONENT_EVENTS.BAG.ITEM_REMOVED,
            ComponentEventFactory.createItemRemoved(this.id, item, reason)
        );
    }

    /**
     * 发射金币变化事件
     */
    protected emitGoldChanged(oldAmount: number, newAmount: number, reason?: string): Promise<ComponentEvent> {
        return this.emitEvent(
            COMPONENT_EVENTS.BAG.GOLD_CHANGED,
            ComponentEventFactory.createGoldChanged(this.id, oldAmount, newAmount, reason)
        );
    }

    /**
     * 发射升级事件
     */
    protected emitLevelUp(oldLevel: number, newLevel: number): Promise<ComponentEvent> {
        return this.emitEvent(
            COMPONENT_EVENTS.RPG.LEVEL_UP,
            ComponentEventFactory.createLevelUp(this.id, oldLevel, newLevel)
        );
    }

    /**
     * 发射经验获得事件
     */
    protected emitExpGained(expGained: number): Promise<ComponentEvent> {
        return this.emitEvent(
            COMPONENT_EVENTS.RPG.EXP_GAINED,
            ComponentEventFactory.createExpGained(this.id, expGained)
        );
    }

    /**
     * 发射战力变化事件
     */
    protected emitPowerChanged(oldPower: number, newPower: number): Promise<ComponentEvent> {
        return this.emitEvent(
            COMPONENT_EVENTS.RPG.POWER_CHANGED,
            ComponentEventFactory.createPowerChanged(this.id, oldPower, newPower)
        );
    }

    /**
     * 发射属性变化事件
     */
    protected emitAttributeChanged(attributeName: string, oldValue: number, newValue: number): Promise<ComponentEvent> {
        return this.emitEvent(
            COMPONENT_EVENTS.RPG.ATTRIBUTE_CHANGED,
            ComponentEventFactory.createAttributeChanged(this.id, attributeName, oldValue, newValue)
        );
    }

    /**
     * 发射技能学会事件
     */
    protected emitSkillLearned(skill: any): Promise<ComponentEvent> {
        return this.emitEvent(
            COMPONENT_EVENTS.RPG.SKILL_LEARNED,
            ComponentEventFactory.createSkillLearned(this.id, skill)
        );
    }

    /**
     * 发射血统获得事件
     */
    protected emitTalentAdded(talent: any): Promise<ComponentEvent> {
        return this.emitEvent(
            COMPONENT_EVENTS.TALENT.ADDED,
            ComponentEventFactory.createTalentAdded(this.id, talent)
        );
    }

    /**
     * 发射血统升级事件
     */
    protected emitTalentUpgraded(talent: any, oldLevel: number, newLevel: number): Promise<ComponentEvent> {
        return this.emitEvent(
            COMPONENT_EVENTS.TALENT.UPGRADED,
            ComponentEventFactory.createTalentUpgraded(this.id, talent, oldLevel, newLevel)
        );
    }

    /**
     * 发射随从添加事件
     */
    protected emitFollowAdded(follow: any): Promise<ComponentEvent> {
        return this.emitEvent(
            COMPONENT_EVENTS.FOLLOW.ADDED,
            ComponentEventFactory.createFollowAdded(this.id, follow)
        );
    }

    /**
     * 发射随从移除事件
     */
    protected emitFollowRemoved(follow: any): Promise<ComponentEvent> {
        return this.emitEvent(
            COMPONENT_EVENTS.FOLLOW.REMOVED,
            ComponentEventFactory.createFollowRemoved(this.id, follow)
        );
    }

    /**
     * 发射任务完成事件
     */
    protected emitTaskCompleted(task: any, rewards?: any[]): Promise<ComponentEvent> {
        return this.emitEvent(
            COMPONENT_EVENTS.TASK.COMPLETED,
            ComponentEventFactory.createTaskCompleted(this.id, task, rewards)
        );
    }

    /**
     * 发射签到事件
     */
    protected emitSigned(signData: any, rewards?: any[], consecutiveDays?: number): Promise<ComponentEvent> {
        return this.emitEvent(
            COMPONENT_EVENTS.SIGN.SIGNED,
            ComponentEventFactory.createSigned(this.id, signData, rewards, consecutiveDays)
        );
    }

    // ==================== 便捷事件监听方法 ====================

    /**
     * 监听装备相关事件
     */
    protected onEquipmentEvents(handlers: {
        onEquipped?: (data: any, event: ComponentEvent) => void | Promise<void>;
        onUnequipped?: (data: any, event: ComponentEvent) => void | Promise<void>;
        onReplaced?: (data: any, event: ComponentEvent) => void | Promise<void>;
        onStatsChanged?: (data: any, event: ComponentEvent) => void | Promise<void>;
    }): void {
        if (handlers.onEquipped) {
            this.onEvent(COMPONENT_EVENTS.EQUIPMENT.EQUIPPED, handlers.onEquipped);
        }
        if (handlers.onUnequipped) {
            this.onEvent(COMPONENT_EVENTS.EQUIPMENT.UNEQUIPPED, handlers.onUnequipped);
        }
        if (handlers.onReplaced) {
            this.onEvent(COMPONENT_EVENTS.EQUIPMENT.REPLACED, handlers.onReplaced);
        }
        if (handlers.onStatsChanged) {
            this.onEvent(COMPONENT_EVENTS.EQUIPMENT.STATS_CHANGED, handlers.onStatsChanged);
        }
    }

    /**
     * 监听背包相关事件
     */
    protected onBagEvents(handlers: {
        onItemAdded?: (data: any, event: ComponentEvent) => void | Promise<void>;
        onItemRemoved?: (data: any, event: ComponentEvent) => void | Promise<void>;
        onItemUsed?: (data: any, event: ComponentEvent) => void | Promise<void>;
        onGoldChanged?: (data: any, event: ComponentEvent) => void | Promise<void>;
    }): void {
        if (handlers.onItemAdded) {
            this.onEvent(COMPONENT_EVENTS.BAG.ITEM_ADDED, handlers.onItemAdded);
        }
        if (handlers.onItemRemoved) {
            this.onEvent(COMPONENT_EVENTS.BAG.ITEM_REMOVED, handlers.onItemRemoved);
        }
        if (handlers.onItemUsed) {
            this.onEvent(COMPONENT_EVENTS.BAG.ITEM_USED, handlers.onItemUsed);
        }
        if (handlers.onGoldChanged) {
            this.onEvent(COMPONENT_EVENTS.BAG.GOLD_CHANGED, handlers.onGoldChanged);
        }
    }

    /**
     * 监听RPG相关事件
     */
    protected onRPGEvents(handlers: {
        onLevelUp?: (data: any, event: ComponentEvent) => void | Promise<void>;
        onExpGained?: (data: any, event: ComponentEvent) => void | Promise<void>;
        onPowerChanged?: (data: any, event: ComponentEvent) => void | Promise<void>;
        onAttributeChanged?: (data: any, event: ComponentEvent) => void | Promise<void>;
        onSkillLearned?: (data: any, event: ComponentEvent) => void | Promise<void>;
    }): void {
        if (handlers.onLevelUp) {
            this.onEvent(COMPONENT_EVENTS.RPG.LEVEL_UP, handlers.onLevelUp);
        }
        if (handlers.onExpGained) {
            this.onEvent(COMPONENT_EVENTS.RPG.EXP_GAINED, handlers.onExpGained);
        }
        if (handlers.onPowerChanged) {
            this.onEvent(COMPONENT_EVENTS.RPG.POWER_CHANGED, handlers.onPowerChanged);
        }
        if (handlers.onAttributeChanged) {
            this.onEvent(COMPONENT_EVENTS.RPG.ATTRIBUTE_CHANGED, handlers.onAttributeChanged);
        }
        if (handlers.onSkillLearned) {
            this.onEvent(COMPONENT_EVENTS.RPG.SKILL_LEARNED, handlers.onSkillLearned);
        }
    }
}
